# coding: utf-8
from jd_oss.MyLdap import MyLdap
from jd_oss.tools import logger
from jd_oss.settings import (
    LDAP_USER_DN,LDAP_DEP_DN,LDAP_GROUP_DN,LDAP_DJANGO_DN
    )

import random
import crypt

flag_mapper = {
    'dep' : str(LDAP_DEP_DN),
    'grp' : str(LDAP_GROUP_DN),
    'user': str(LDAP_USER_DN),
    'django': str(LDAP_DJANGO_DN)
}

class UserError(Exception):
    pass

class UserTools(object):
    _ldap = MyLdap.get_ldap()

    @staticmethod
    def _search(**kwargs):
        """ ldap 基础搜索函数
            返回一个包含LDAPSearchResult对象的列表
            Returns:
                [<LDAPSearchResult>,<LDAPSearchResult>]
        """
        for k,v in kwargs.iteritems():
            if k != 'dn':
                kwargs.pop(k)
                kwargs['filterstr'] = "(%s=%s)" % (k,v)
                break

        return UserTools._ldap.search(**kwargs)

    @staticmethod
    def _add_user_to(username,to,flag):
        """ 添加用户到指定用户组 """
        dn = 'cn=%s,%s' % (to, flag_mapper[flag])
        op = [(0,'memberUid',username)]
        UserTools._ldap.modify(dn,op)

    @staticmethod
    def add_user_to_group(username,group):
        flag = 'grp'
        UserTools._add_user_to(username,group,flag)

    @staticmethod
    def add_user_to_dep(username,dep):
        flag = 'dep'
        UserTools._add_user_to(username,dep,flag)

    @staticmethod
    def add_user_to_django(username,django):
        flag = 'django'
        UserTools._add_user_to(username,django,flag)

    @staticmethod
    def get_user(username):
        """ 从ldap获取指定用户的信息,
            返回一个 LDAPSearchResult 对象,或对象列表
            Returns:
                len(r) > 1  : [<LDAPSearchResult>,<LDAPSearchResult>]
                len(r) == 1 : <LDAPSearchResult>
        """
        kwargs = {
            'dn' : str(LDAP_USER_DN),
            'uid':  username
            }
        r =  UserTools._search(**kwargs)

        if r:
            return r
        else:
            return None

    @staticmethod
    def get_all(flag):
        """ 获取当前指定flag的所有条目cn和描述
            Returns:
                entry(dict) : {
                        'yunwei':'运维'
                    }
        """

        kwargs = {
            'dn' : flag_mapper[flag],
            'cn' : '*'
        }
        r = UserTools._search(**kwargs)
        return r

    @staticmethod
    def get_user_dep(username):
        """ 获取用户所属的部门
            Returns: 返回一个字典对象.
                {
                  "yunwei": "运维",
                  "jszczx": "技术支持中心"
                }
        """
        kwargs = {
            'dn': str(LDAP_DEP_DN),
            'memberUid' : username
        }
        return { i["cn"]:i['description']
                 for i in UserTools._search(**kwargs)}

    @staticmethod
    def get_user_group(username):
        """ 获取用户所属的用户组
            Returns: 返回一个字典对象.
                {
                  "django": "django应用",
                }
        """
        kwargs = {
            'dn': str(LDAP_GROUP_DN),
            'memberUid' : username
        }
        return { i["cn"]:( i['description']
                            if i.has_attribute('description') else u"[%s]组描述未定义" % i["cn"][0]
                         )
                    for i in UserTools._search(**kwargs)
                }


    @staticmethod
    def is_member_of_group(group,username):
        """ 判断成员是否是某组的成员
            Returns:
                True or False
        """
        result = False
        kwargs = {
            'dn': str(LDAP_GROUP_DN),
            'cn': group
        }

        lgroup = UserTools._search(**kwargs)
        if lgroup:
            result = username in lgroup.get_attr_values("memberUid")

        return result


    @staticmethod
    def is_member_of_dep(department,username):
        """ 判断成员是否是某部门的成员
            Returns:
                True or False
        """
        kwargs = {
            'dn': str(LDAP_DEP_DN),
            'cn': group
        }

        lgroup = UserTools._search(**kwargs)[0]
        return username in lgroup.get_attr_values("memberUid")

    @staticmethod
    def add_user(attrs):
        """ 添加用户到ldap信息树 """
        username = attrs['uid']
        if username:
            dn = 'uid=%s,%s' % (username,LDAP_USER_DN)
            UserTools._ldap.add(dn,attrs)
        else:
            raise UserError,"添加用户出错,属性参数错误."

    @staticmethod
    def delete_user(username):
        """ 删除指定用户条目信息. """
        org_list = []
        op = []
        # 删掉用户条目
        dn = 'uid=%s,%s' % (username,LDAP_USER_DN)
        UserTools._ldap.delete(dn)

        get_all = UserTools.get_all
        # 遍历所有分组条目 (用户组，django分组, 部门)
        org_list = get_all('grp') + get_all('django') + get_all('dep')
        for entry in org_list:
            dn = entry.dn
            if entry.has_attribute('memberUid') \
            and username in entry['memberUid']:
                # 删除用户在组中的信息.
                ops = [(1,'memberUid',username)]
                UserTools._ldap.modify(dn,ops)

    @staticmethod
    def gen_uidNumber1():
        """ 生成uidNumber 1 - 1000 """
        now_uid_nums = [ u['uidNumber'] for u in UserTools.get_all('user') ]
        for i in xrange(1,1001):
            if i not in now_uid_nums:
                return i
        else:
            raise UserError,"1 - 1000的uidNumber耗尽,请调整限制."


def gen_rand_pwd(num):
    """
    生成随机密码
        num:产生的密码长度
    """
    seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    salt_list = []
    for i in range(num):
        salt_list.append(random.choice(seed))
    salt = ''.join(salt_list)
    return salt


def gen_sha512(salt, password):
    return crypt.crypt(password, '$6$%s$' % salt)
